home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 1
/
Atari Mega Archive - Volume 1.iso
/
language
/
sozobon2.zoo
/
tools
/
globs.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-12-13
|
6KB
|
373 lines
/* Copyright (c) 1988 by Sozobon, Limited. Author: Johann Ruegg
*
* Permission is granted to anyone to use this software for any purpose
* on any computer system, and to redistribute it freely, with the
* following restrictions:
* 1) No charge may be made other than reasonable charges for reproduction.
* 2) Modified versions must be clearly marked as such.
* 3) The authors are not responsible for any harmful consequences
* of using this software, even if they result from defects in it.
*
* Program to remove local symbols from Alcyon .o's or archives
*
* 02OCT88
* dal: fixed temp file rename problem using _splitpath/_makepath
* and made several error handling changes. Also added the
* '-s' switch for "silent" operation.
*/
#include <stdio.h>
#include <ar.h>
#define MAXGL 2048
struct hdr {
int magic;
long tsize, dsize, bsize;
long syms;
long f1,f2;
int f3;
} h;
struct sym {
char name[8];
char flags;
long value;
};
FILE *outfd;
int nnew;
int s_flag = FALSE; /* operate silently */
char *filename = NULL; /* current filename */
int many = FALSE; /* more than one source file */
usage()
{
fprintf(stderr, "usage: globs [-s] file...\n");
fprintf(stderr, " remove non-essential symbols\n");
exit(1);
}
main(argc, argv)
int argc;
char *argv[];
{
while(--argc && (**++argv == '-'))
doopt(*argv);
if (argc < 1)
usage();
many = (argc > 1);
while (argc--)
doname(*argv++);
putchar('\n');
}
doopt(s)
register char *s;
{
while (*++s)
switch (*s) {
#ifdef G_FLAG
case 'g':
g_flag = TRUE;
#endif
case 's':
s_flag = TRUE;
default:
fprintf(stderr, "globs: illegal option '%c'\n", *s);
usage();
}
}
doname(s)
char *s;
{
FILE *fd, *fopen();
int i, n, nlost;
char pbuf[128], drive[4], path[128];
filename = s;
fd = fopen(s, "rb");
if (fd == NULL) {
fprintf(stderr, "globs: can't open '%s'\n", s);
return;
}
_splitpath(s, drive, path, NULL, NULL);
_makepath(pbuf, drive, path, "_globs", "tmp");
outfd = fopen(pbuf, "wb");
if (outfd == NULL) {
fprintf(stderr, "globs: can't open tmp file\n");
fclose(fd);
exit(EXIT_FAILURE);
}
if (many && !s_flag)
printf("processing %s\n", s);
if (i = dohdr(fd)) {
if (i == -1)
doarch(fd);
else {
startsyms();
for (n=0; n<i; n++)
dosym(fd, n);
nlost = i - nnew;
if (!s_flag)
printf("removed %d symbols\n", nlost);
if (nlost == 0) {
fclose(fd);
return;
}
rewind(fd);
redo(fd);
dorel(fd);
}
} else
exit(1);
fclose(fd);
fclose(outfd);
if (unlink(s) || rename(pbuf, s)) {
fprintf(stderr, "globs: unlink/rename error on '%s'\n", s);
exit(EXIT_FAILURE);
}
}
dohdr(fd)
FILE *fd;
{
int i;
long len;
fread(&h, 2, 1, fd);
if (h.magic == ARMAG1)
return -1;
i = fread((char *)&h + 2, sizeof(h) - 2, 1, fd);
if (i != 1 || h.magic != 0x601a) {
printf("globs: bad header on '%s'\n", filename);
return 0;
}
len = h.tsize + h.dsize;
fseek(fd, len, 1);
return(h.syms / sizeof(struct sym));
}
struct newsym {
int oldnum;
struct sym sy;
} ns[MAXGL];
findx(x)
{
register i;
x >>= 3;
for (i=0; i<nnew; i++)
if (ns[i].oldnum == x) {
x = i;
goto okay;
}
printf("globs: can't find sym %d in '%s'\n", x, filename);
exit(EXIT_FAILURE);
okay:
x = (x<<3) + 4;
return x;
}
redo(fd)
FILE *fd;
{
register i;
long oldsyms;
fread(&h, sizeof(h), 1, fd);
oldsyms = h.syms;
h.syms = (long)nnew * sizeof(struct sym);
fwrite(&h, sizeof(h), 1, outfd);
lcopy(fd, h.tsize+h.dsize);
fseek(fd, oldsyms, 1);
for (i=0; i<nnew; i++)
fwrite(&ns[i].sy, sizeof(struct sym), 1, outfd);
}
#define BSIZE 1024
lcopy(fd, len)
FILE *fd;
long len;
{
int n;
char buf[BSIZE];
while (len) {
n = len > BSIZE ? BSIZE : len;
fread(buf, n, 1, fd);
fwrite(buf, n, 1, outfd);
len -= n;
}
}
startsyms()
{
nnew = 0;
}
dosym(fd, oldn)
FILE *fd;
{
struct sym s;
int i;
i = fread(&s, sizeof(s), 1, fd);
if (i != 1)
return;
if (not_glob(s.flags))
return;
ns[nnew].sy = s;
ns[nnew].oldnum = oldn;
nnew++;
}
fill8(s)
char *s;
{
int i;
for (i=0; i<8; i++)
if (s[i] == 0)
putchar(' ');
}
char *fname[] = {
"?0?", "bss", "text", "?3?", "data",
"?5?", "?6?", "?7?"
};
not_glob(x)
{
x &= 0xff;
if (x & 0x20)
return 0;
x &= ~0x20;
if (x == 0x88)
return 0;
return 1;
}
#ifdef NEVER
sflags(x)
{
x &= 0xff;
if (x & 0x20)
printf("global ");
x &= ~0x20;
if (x == 0x88)
printf("external abs");
else if (x == 0xc0)
printf("equ abs");
else if (x == 0xd0)
printf("equ reg abs");
else {
x &= 7;
printf(fname[x]);
}
}
#endif
doarch(fd)
FILE *fd;
{
struct ar_hdr a;
int i, n, nlost, x;
long astart, ostart, ftell();
i = ARMAG1;
fwrite(&i, sizeof(int), 1, outfd);
more:
i = fread(&a, sizeof(a), 1, fd);
if (i != 1)
goto out;
if (!s_flag)
printf("\n(%.18s):\n", a.ar_name);
ostart = ftell(fd);
astart = ostart + a.ar_size;
i = dohdr(fd);
if (i <= 0)
return;
startsyms();
for (n=0; n<i; n++)
dosym(fd, n);
nlost = i-nnew;
if (!s_flag)
printf("removed %d symbols\n", nlost);
a.ar_size = sizeof(h) + 2*(h.tsize+h.dsize) +
nnew*sizeof(struct sym);
fwrite(&a, sizeof(a), 1, outfd);
fseek(fd, ostart, 0);
redo(fd);
dorel(fd);
fseek(fd, astart, 0);
goto more;
out:
x = ftell(outfd);
x &= 0xff;
if (x)
zeroes(0x100 - x);
}
char zbuf[0x100];
zeroes(n)
{
if (!s_flag)
printf("fill %d\n", n);
fwrite(zbuf, n, 1, outfd);
}
dorel(fd)
FILE *fd;
{
long num, i;
long here, ftell();
int x;
here = ftell(fd);
num = (h.tsize + h.dsize)/((long) sizeof(int));
if (!s_flag)
printf("at %lx, %ld words\n", here, num);
for (i=0; i<num; i++) {
fread(&x, sizeof(int), 1, fd);
fwrite(&x, sizeof(int), 1, outfd);
switch (x) {
case 7:
case 0:
break;
case 5:
fread(&x, sizeof(int), 1, fd);
i++;
if ((x & 7) == 4)
x = findx(x);
fwrite(&x, sizeof(int), 1, outfd);
break;
default:
printf("?%x? ", x);
}
}
}